﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DimsMapper.Modules
{
    public static class Utilites
    {
        public static int GetInt(ref byte[] data, ref int position)
        {
            int value = data[position++] << 24;
            value |= data[position++] << 16;
            value |= data[position++] << 8;
            return value | data[position++];
        }

        public static ushort GetShort(ref byte[] data, ref int position)
        {
            ushort value = (ushort)(data[position++] << 8);
            value |= data[position++];
            return value;
        }

        public static void GetCritterFileName(ref string baseName, int artFID)
        {
            int commaPos = baseName.IndexOf(',');

            //int index = artFID & 0x00000FFF;
            int ID1 = (artFID & 0x0000F000) >> 12;
            int ID2 = (artFID & 0x00FF0000) >> 16;
            int ID3 = (artFID & 0x70000000) >> 28;

            // Изменение индекса
            if (ID2 == 0x1B || ID2 == 0x1D || ID2 == 0x1E || ID2 == 0x37 ||
                ID2 == 0x39 || ID2 == 0x3A || ID2 == 0x21 || ID2 == 0x40)
            {
                if (commaPos != -1) {
                    commaPos++;
                    int secondComma = baseName.IndexOf(',', commaPos);

                    int len = (secondComma == -1) ? baseName.Length : secondComma;
                    len -= commaPos;
                    int newIndex = int.Parse(baseName.Substring(commaPos, len));

                    //index = newIndex;

                    baseName = LstFiles.FrmNameFile((int)Object.Types.Critter, newIndex);

                    commaPos = baseName.IndexOf(',');
                } else {
                    // ошибка - нет индекса для переопределения
                }
            }
            StringBuilder frmName = new StringBuilder((commaPos != -1) ? baseName.Remove(commaPos) : baseName, 12);

            // Получение суффиксов
            char suffix1, suffix2;
            if (!getSuffixes(ID1, ID2, out suffix1, out suffix2)) {
                // bad artFID
                return;
            }

            frmName.Append(suffix1);
            frmName.Append(suffix2);
            frmName.Append(".fr" + (char)((ID3 != 0) ? ('0' + ID3 - 1) : 'm'));
            baseName = frmName.ToString();
        }

        static bool getSuffixes(int ID1, int ID2, out char suffix1, out char suffix2)
        {
            if (ID1 >= 0x0B) {
                suffix1 = '\0';
                suffix2 = '\0';
                return false;
            }
            if (ID2 >= 0x26 && ID2 <= 0x2F) {
                suffix2 = (char)(ID2 + 0x3D);

                if (ID1 == 0) {
                    suffix1 = '\0';
                    suffix2 = '\0';
                    return false;
                }
                suffix1 = (char)(ID1 + 'c');
                return true;
            }

            if (ID2 == 0x24) {
                suffix2 = 'h';
                suffix1 = 'c';
                return true;
            }

            if (ID2 == 0x25) {
                suffix2 = 'j';
                suffix1 = 'c';
                return true;
            }

            if (ID2 == 0x40) {
                suffix2 = 'a';
                suffix1 = 'n';
                return true;
            }

            if (ID2 >= 0x30) {
                suffix2 = (char)(ID2 + 0x31);
                suffix1 = 'r';
                return true;
            }

            if (ID2 >= 0x14) {
                suffix2 = (char)(ID2 + 0x4D);
                suffix1 = 'b';
                return true;
            }

            if (ID2 == 0x12) {
                if (ID1 == 0x01) {
                    suffix1 = 'd';
                    suffix2 = 'm';
                    return true;
                }

                if (ID1 == 0x04) {
                    suffix1 = 'g';
                    suffix2 = 'm';
                    return true;
                }

                suffix1 = 'a';
                suffix2 = 's';
                return true;
            }

            if (ID2 == 0x0D) {
                if (ID1 > 0x00) {
                    suffix1 = (char)(ID1 + 'c');
                    suffix2 = 'e';
                    return true;
                }

                suffix1 = 'a';
                suffix2 = 'n';
                return true;
            }
            suffix2 = (char)(ID2 + 'a');

            if (ID2 <= 1 && ID1 > 0) {
                suffix1 = (char)(ID1 + 'c');
                return true;
            }

            suffix1 = 'a';
            return true;
        }

        // возвращает позицию на карте (прямые координаты worldX/Y) относительно позиции указанных экранных координат x/y (0-100)
        public static void GetWorldCoord(int x, int y, int w, int h,ref int worldX, ref int worldY)
        {
           x = 99 - x;
            worldX = 4752 - (48 * x) + (y << 5) - (w >> 1); // 320 размер вьюпорта карты
            worldY = (12 * x) + (24 * y) - (h >> 1); //240;
        }

        public static void GetTileWorldCoord(int tileX, int tileY, out int worldX, out int worldY)
        {
           worldX = 4752 + (32 * tileY) - (48 * tileX);
           worldY = (24 * tileY) + (12 * tileX);
        }

        // возвращает позицию на карте, из координат hexX/Y
        public static void GetHexWorldCoord(int hexX, int hexY, out int mapX, out int mapY)
        {
            //  mapX = 4816 - (32 * ((X + 1) >> 1) + (16 * (X >> 1)) - (Y * 16)); //ver1
            //  mapY = ((12 * (X >> 1)) + (Y * 12)) + 11; // + 8

            mapX = 4816 - ((((hexX + 1) >> 1) << 5 )+ ((hexX >> 1) << 4) - (hexY << 4)); //ver1
            mapY = ((12 * (hexX >> 1)) + (hexY * 12)) + 11; // + 8
        }

        // возвращает позицию гекса в hexX/Y, относительно экранных коодинат x/y и текущей позиции на карте worldX/Y 
        public static void GetCursorHex(int X, int Y, int worldX, int worldY, out int hexX, out int hexY)
        {
            const int x0 = 4800; //int x0 = 4816;
            const int y0 = 6;    //int y0 = 11;
            X += worldX;
            Y += worldY;

            int nx;
            if (X - x0 < 0)
                nx = (X - x0 + 1) / 16 - 1;
            else
                nx = (X - x0) / 16;

            int ny;
            if (Y - y0 < 0)
                ny = (Y - y0 + 1) / 12 - 1;
            else
                ny = (Y - y0) / 12;

            if (Math.Abs(nx) % 2 != Math.Abs(ny) % 2)  nx--;

            int xhBase = x0 + 16 * nx;
            int yhBase = y0 + 12 * ny;

            hexX = (4 * (yhBase - y0) - 3 * (xhBase - x0)) / 96;
            hexY = (yhBase - y0) / 12 - hexX / 2;

            int dx = X - xhBase;
            int dy = Y - yhBase;

            switch (dy) {
            case 0:
                if (dx < 12) {
                    hexY--;
                    break;
                }
                if (dx > 18) {
                    if (hexX % 2 == 1) hexY--;
                    hexX--;
                }
                break;
            case 1:
                if (dx < 8) {
                    hexX--;
                    break;
                }
                if (dx > 23) {
                    if (hexX % 2 == 1) hexY--;
                    hexX--;
                }
                break;
            case 2:
                if (dx < 4) {
                    hexY--;
                    break;
                }
                if (dx > 28) {
                    if (hexX % 2 == 1) hexY--;
                    hexX--;
                }
                break;
            }
        }

        // возвращает позицию квадрата в tileX/Y, относительно экранных коодинат x/y и текущей позиции на карте worldX/Y
        public static void GetCursorTile(int X, int Y, int wX, int wY, out int tileX, out int tileY)
        {
           int off_x = -4800 + (wX + X);
           int off_y = wY + Y;

           int xx = off_x - off_y * 4 / 3;

           tileX = xx / 64;
           if (xx >= 0) tileX++;

           tileX = -tileX;

           int yy = off_y + off_x / 4;
           tileY = yy / 32;
           if (yy < 0) tileY--;
        }

        // получает tile из координат hexX/Y
        public static int GetHex(int hexX, int hexY)
        {
            return hexY * 200 + hexX;
        }

        public static int GetHex(int x, int y, int xW, int yW)
        {
            int tileX, tileY;
            GetCursorHex(x, y, xW, yW, out tileX, out tileY);
            return GetHex(tileX, tileY);
        }

        // получает координаты hexX/Y из tile
        public static void GetHexXY(int tile, out int hexX, out int hexY)
        {
            hexX = tile % 200;
            hexY = tile / 200;
        }
    }
}
